package com.xipu.yygh.order.controller;


import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.xipu.yygh.common.result.R;
import com.xipu.yygh.model.order.OrderInfo;
import com.xipu.yygh.order.service.OrderInfoService;
import com.xipu.yygh.vo.order.OrderCountQueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单表 前端控制器
 * </p>
 *
 * @author gql
 * @since 2022-05-12
 */
@RestController
@RequestMapping("/api/order/orderInfo")
public class OrderInfoController {
    /**
     * 订单表
     */
    @Autowired
    private OrderInfoService orderInfoService;

    //*************************流量控制👇*************************

    /**
     * 创建OrderInfoController对象时执行,设定规则。
     */
    public OrderInfoController() {
        initRule();
    }

    /**
     * 热点值限流规则
     */
    private void initRule() {
        // 资源名称
        ParamFlowRule pRule = new ParamFlowRule("submitOrder")
                //限流第一个参数
                .setParamIdx(0)
                //单机阈值
                .setCount(5);
        // 针对 热点参数值单独设置限流 QPS 阈值，而不是全局的阈值.
        ParamFlowItem item1 = new ParamFlowItem().setObject("10001")
                //热点值类型
                .setClassType(String.class.getName())
                //热点值 QPS 阈值
                .setCount(1);
        List<ParamFlowItem> list = new ArrayList<>();
        list.add(item1);
        pRule.setParamFlowItemList(list);
        ParamFlowRuleManager.loadRules(Collections.singletonList(pRule));
    }

    /**
     * 热点值超过 QPS 阈值，返回结果
     * 兜底方法: 参数与接口参数保持一致,并添加额外的BlockException参数
     * @param hoscode 医院编号
     * @param scheduleId 排班编号
     * @param patientId 病人编号
     * @param e exception
     * @return r
     */
    public R submitOrderBlockHandler(String hoscode, String scheduleId, Long patientId, BlockException e) {
        return R.error().message("系统业务繁忙，请稍后预约");
    }

    /**
     * 生成挂号订单(流量控制版)
     * @param hoscode 医院编号
     * @param scheduleId 排班编号
     * @param patientId 病人编号
     * @return r(订单Id)
     */
    @PostMapping("auth2/submitOrder/{hoscode}/{scheduleId}/{patientId}")
    @SentinelResource(value = "submitOrder", blockHandler = "submitOrderBlockHandler")
    public R submitOrders(
            @PathVariable String hoscode,
            @PathVariable String scheduleId,
            @PathVariable Long patientId) {
        Long orderId = 1L;
        return R.ok().data("orderId", orderId);
    }
    //*************************流量控制👆*************************


    /**
     * 生成挂号订单
     * @param scheduleId 排班Id
     * @param patientId 病人Id
     * @return r(订单Id)
     */
    @PostMapping("auth/submitOrder/{scheduleId}/{patientId}")
    public R submitOrder(
            @PathVariable String scheduleId,
            @PathVariable Long patientId) {
        Long orderId = this.orderInfoService.saveOrder(scheduleId, patientId);
        return R.ok().data("orderId", orderId);
    }


    /**
     * 查询订单详情
     * @param orderId 订单Id
     * @return r
     */
    @GetMapping("auth/getOrders/{orderId}")
    public R getOrders(@PathVariable Long orderId) {
        OrderInfo orderInfo = this.orderInfoService.getOrderInfo(orderId);
        return R.ok().data("orderInfo", orderInfo);
    }

    /**
     * 取消预约
     * @param orderId 订单Id
     * @return r
     */
    @GetMapping("/auth/cancelOrder/{orderId}")
    public R cancelOrder(@PathVariable("orderId") Long orderId) {
        Boolean flag = this.orderInfoService.cancelOrder(orderId);
        return R.ok().data("flag", flag);
    }

    /**
     * 获取订单统计数据
     * @param orderCountQueryVo 订单数量统计Vo
     * @return map
     */
    @PostMapping("/inner/getCountMap")
    public Map<String, Object> getCountMap(@RequestBody OrderCountQueryVo orderCountQueryVo) {
        return this.orderInfoService.getCountMap(orderCountQueryVo);
    }
}
